export default class ElemMovable {
  constructor(option) {
    let anchor, target, getHook, getPosition, onMoveEnd, onmousemove, onmouseup, onmousedown;
    anchor = option.anchor;
    target = option.target;
    getHook = (option, name, defaultHook) => {
      return typeof option[name] === 'function' ? option[name] : defaultHook;
    };
    getPosition = getHook(option, 'getPosition', (el, style) => style);
    onMoveEnd = getHook(option, 'onMoveEnd', () => {});
    onmousemove = (e) => {
      e.preventDefault();
      e.stopPropagation();
      if (target.startPoint) {
        let { width, height } = target.startPoint;
        let offset = (target.offset = {
          x: e.pageX - target.startPoint.x,
          y: e.pageY - target.startPoint.y,
        });
        let top = target.startPoint.top + offset.y;
        let left = target.startPoint.left + offset.x;
        let style = getPosition(target, {
          width: width,
          height: height,
          x: left,
          y: top,
          left: left,
          top: top,
          right: window.innerWidth - left - width,
          bottom: window.innerHeight - top - height,
        });
        ['top', 'right', 'bottom', 'left'].forEach((key) => {
          if (typeof style[key] === 'number') style[key] += 'px';
        });
        Object.keys(style).forEach((key) => {
          target.style[key] = style[key];
        });
        offset = null;
        style = null;
      }
    };
    onmouseup = (e) => {
      if (e) {
        e.preventDefault();
        e.stopPropagation();
      }
      target.startPoint = null;
      document.body.style.cursor = target.cursor || 'unset';
      document.body.style.userSelect = target.userSelect || 'auto';
      document.body.removeEventListener('mouseup', onmouseup);
      document.body.removeEventListener('mousemove', onmousemove);
      onMoveEnd(target);
    };
    onmousedown = (e) => {
      e.preventDefault();
      e.stopPropagation();
      let { top, right, bottom, left } = window.getComputedStyle(target);
      let width = target.offsetWidth;
      let height = target.offsetHeight;
      target.startPoint = {
        x: e.pageX,
        y: e.pageY,
        width: width,
        height: height,
        top: parseFloat(top) || 0,
        right: parseFloat(right) || 0,
        bottom: parseFloat(bottom) || 0,
        left: parseFloat(left) || 0,
      };
      target.cursor = document.body.style.cursor;
      target.userSelect = document.body.style.userSelect;
      document.body.style.cursor = 'move';
      document.body.style.userSelect = 'none';
      document.body.addEventListener('mouseup', onmouseup);
      document.body.addEventListener('mousemove', onmousemove);
    };

    anchor.addEventListener('mousedown', onmousedown);

    this.destroy = () => {
      anchor.removeEventListener('mousedown', onmousedown);
      onmouseup();
      onmouseup = null;
      onmousedown = null;
      onmousemove = null;
      onMoveEnd = null;
      anchor = null;
      target = null;
      getHook = null;
      getPosition = null;
    };
  }
}
